package com.friend.chat.webrtc;

import android.util.Log;

import androidx.annotation.NonNull;

import org.webrtc.DataChannel;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpReceiver;
import org.webrtc.SdpObserver;
import org.webrtc.SessionDescription;

import java.util.ArrayList;
import java.util.List;

/**
 * @author batie fancy
 * @des
 * @date 2023/4/6
 */
public class PeerManager implements SdpObserver {

    private static final String TAG = "PeerManager";
    /* private final String mUserId,mToUid;*/
    private PeerConnection mPeerConnection;
    private SessionDescription mSessionDescription;

    private final List<IceCandidate> queuedRemoteCandidates = new ArrayList<>();

    private IWebRtcCallback mCallback;

    private boolean isOffer;

    public PeerManager(PeerConnectionFactory factory, List<PeerConnection.IceServer> list, @NonNull IWebRtcCallback callback) {
        mCallback = callback;
        createPeerConnection(factory, list);
    }

    private void createPeerConnection(PeerConnectionFactory factory, List<PeerConnection.IceServer> list) {
        PeerConnection.RTCConfiguration rtcConfiguration = new PeerConnection.RTCConfiguration(list);
        mPeerConnection = factory.createPeerConnection(rtcConfiguration, new PeerConnection.Observer() {
            @Override
            public void onSignalingChange(PeerConnection.SignalingState signalingState) {

            }

            @Override
            public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {

            }

            @Override
            public void onIceConnectionReceivingChange(boolean b) {

            }

            @Override
            public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {

            }

            @Override
            public void onIceCandidate(IceCandidate iceCandidate) {
                //setRemoteDescription后，会回调这里
                mCallback.sendIceCandidate(iceCandidate.sdpMid, iceCandidate.sdpMLineIndex, iceCandidate.sdp);

            }

            @Override
            public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {

            }

            @Override
            public void onAddStream(MediaStream mediaStream) {
                mCallback.onRemoteStream(mediaStream);
            }

            @Override
            public void onRemoveStream(MediaStream mediaStream) {

            }

            @Override
            public void onDataChannel(DataChannel dataChannel) {

            }

            @Override
            public void onRenegotiationNeeded() {

            }

            @Override
            public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {

            }
        });
    }

    public void setOffer(boolean isOffer) {
        this.isOffer = isOffer;
    }

    public void setRemoteDescription(SessionDescription sessionDescription) {
        if (mPeerConnection != null) {
            mPeerConnection.setRemoteDescription(this, sessionDescription);
        }
    }

    public synchronized void addRemoteIceCandidate(final IceCandidate candidate) {
        if (mPeerConnection != null) {
            synchronized (PeerManager.class) {
                mPeerConnection.addIceCandidate(candidate);

            }
        }
    }

    public void addStream(MediaStream localStream) {
        if (mPeerConnection != null) {
            mPeerConnection.addStream(localStream);
        }
    }

    public void createOffer() {
        if (mPeerConnection != null) {
            mPeerConnection.createOffer(this, offerOrAnswerConstraint());
        }
    }

    public void createAnswer() {
        if (mPeerConnection != null) {
            mPeerConnection.createAnswer(this, offerOrAnswerConstraint());
        }
    }

    private MediaConstraints offerOrAnswerConstraint() {
        MediaConstraints mediaConstraints = new MediaConstraints();
        ArrayList<MediaConstraints.KeyValuePair> keyValuePairs = new ArrayList<>();
        keyValuePairs.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
        keyValuePairs.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
        mediaConstraints.mandatory.addAll(keyValuePairs);
        return mediaConstraints;
    }

    /**
     * SdpObserver
     * createOffer之后回调
     * createAnswer之后也会回调（接收者）
     */
    @Override
    public void onCreateSuccess(SessionDescription sessionDescription) {
        Log.e("---->", "SDP创建成功" + sessionDescription.type);
        mSessionDescription = sessionDescription;
        if (mPeerConnection != null) {
            mPeerConnection.setLocalDescription(this, sessionDescription);
        }
    }

    /**
     * SdpObserver
     * setLocalDescription之后回调（offer,answer)
     * setRemoteDescription 之后也会回调
     * 有三种可能
     */
    @Override
    public void onSetSuccess() {
        if (mPeerConnection != null) {
            //发送者
            if (isOffer) {
                if (mPeerConnection.getRemoteDescription() == null) {
                    //发起者,发送本地sdp到信令服务器
                    mCallback.sendOffer(mSessionDescription);
                }
            } else {
                //接收者，发送本地sdp到信令服务器
                if (mPeerConnection.getLocalDescription() != null) {
                    mCallback.sendAnswer(mSessionDescription);
                } else {
                    // setRemoteDescription 不操作
                }
            }
        }
    }

    @Override
    public void onCreateFailure(String s) {

    }

    @Override
    public void onSetFailure(String s) {

    }
}
